package com.relax.mybatis.encrypt.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.relax.mybatis.encrypt.algorithm.Base64;
import com.relax.mybatis.encrypt.algorithm.RSA;
import com.relax.mybatis.encrypt.algorithm.SM4;

/**
 * @author relax
 * @date 2022/07/05
 * @desc
 */
public class KeyGenerator {

    public static String generateSM4Key() throws Exception {
        return SM4.generateKey();
    }

    public static String[] generateSM2Keys() throws Exception {
        ECGenParameterSpec eCGenParameterSpec = new ECGenParameterSpec("sm2p256v1");
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", (Provider)new BouncyCastleProvider());
        keyPairGenerator.initialize(eCGenParameterSpec);
        keyPairGenerator.initialize(eCGenParameterSpec, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return new String[] {Base64.encodeToString(keyPair.getPublic().getEncoded()),
            Base64.encodeToString(keyPair.getPrivate().getEncoded())};
    }

    public static String[] generateRSAKeys() throws Exception {
        Map<String, Object> keyMap = RSA.getKeyMap();
        String publicKey = RSA.getPublicKey(keyMap);
        String privateKey = RSA.getPrivateKey(keyMap);
        return new String[] {publicKey, privateKey};
    }

    public static PublicKey createPublicKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(key));
        return getKeyFactory("EC").generatePublic(x509EncodedKeySpec);
    }

    public static PrivateKey createPrivateKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(key));
        return getKeyFactory("EC").generatePrivate(pKCS8EncodedKeySpec);
    }

    public static KeyFactory getKeyFactory(String algorithm) throws NoSuchAlgorithmException {
        return KeyFactory.getInstance(algorithm, (Provider)new BouncyCastleProvider());
    }
}
